﻿#ifndef __BASE_EVENTDISPATCHER_H__
#define __BASE_EVENTDISPATCHER_H__
/*
Email me@dreamyouxi.com
*/
#include <unordered_map>
#include <vector>
#include <string>
#include <iostream>
#include "EventDelegate.h"
#include "Singleton.hpp"
#include "ThreadSafeQueue.hpp"
namespace Base
{
	using namespace std;
	class EventDelegate;
 
	class EventCallWrapper
	{
	public:
		 EventCallWrapper(void *obj, EventCallBackFunc*cb)
		{
			this->obj = obj;
			this->cb = cb;
		}
		void *obj = nullptr;
		EventCallBackFunc*cb = nullptr;
		void * InVoke(const std::string  &pb)
		{
			if (cb && obj)
			{
				return cb(obj, pb);
			}
		}
	};
	class EventDispatcher
	{
		SingletonH(EventDispatcher)
	public:
		void AutoRegisterAllStaticEvents();
		void ProcessOneLoop();
		void PostEvent(int event_id, const std::string&pb)
		{
			auto&it = _map_id.find(event_id);
			if (it == _map_id.end())
			{
				return;
			}
			auto & bluck = it->second;
			for (auto &cb : bluck)
			{
				void *ret = cb.InVoke(pb);
			}
		}
		void PostEvent(const std::string & event_name, const std::string&pb)
		{
			auto&it = _map_name.find(event_name);
			if (it == _map_name.end())
			{
				return;
			}
			auto & bluck = it->second;
			for (auto &cb : bluck)
			{
				void *ret = cb.InVoke(pb);
			}
		}
		void PostEventStatic(const std::string & event_name, const std::string&pb)
		{
			this->_queue_recv_static.push(std::make_pair(event_name, pb));
		}
		void AddEventDelegate(int event_id, EventDelegate *delegate, EventCallBackFunc cb)
		{
			_map_id[event_id].push_back(EventCallWrapper(delegate, cb));
		/*	auto & bluck = _map_id.find(event_id);
			if (bluck == _map_id.end())
			{
				_map_id[event_id] = std::move(std::vector<EventCallWrapper>());
				_map_id[event_id].push_back(EventCallWrapper(delegate, cb));
				return;
			}
			bluck->second.push_back(EventCallWrapper(delegate, cb));*/
		}
		void AddEventDelegate(const std::string & event_name, EventDelegate *delegate, EventCallBackFunc cb)
		{
			_map_name[event_name].push_back(EventCallWrapper(delegate,cb));
			/*auto & bluck = _map_name.find(event_name);
			if (bluck == _map_name.end())
			{
				_map_name[event_name] = std::move(std::vector<EventCallWrapper>());
				_map_name[event_name].push_back(EventCallWrapper(delegate, cb));
				return;
			}
			std::cout << "add";
			bluck->second.push_back(EventCallWrapper(delegate, cb));*/
		}

		void AddStaticEvent(const std::string & name, EventCallBackFunc *cb);
	private:
		void ProcessStaticEventQueue();
		std::unordered_map<int, std::vector<EventCallWrapper>> _map_id;
		std::unordered_map<std::string, std::vector<EventCallWrapper>> _map_name;

		std::unordered_map<std::string,Base:: EventCallBackFunc*  > _map_static;
		typedef	ThreadSafeQueue<std::pair<std::string, std::string>> QueueSafe;
		typedef	std::queue<std::pair<std::string, std::string>> Queue;

		QueueSafe _queue_recv_static;
	};

}


#endif
